package main;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.*;
import java.util.Random;

import javax.swing.*;

public class MousePanelFrame extends JFrame
{
	private final int DURATION = 3000;
	
	private final Random rand = new Random();
	private final MousePanel panel;
	
	public MousePanelFrame( MousePanel panel )
	{
		this.panel = panel;
		this.getContentPane().add( panel, BorderLayout.CENTER );
		this.getContentPane().add( makeButton(), BorderLayout.SOUTH );
		
		this.setTitle( "Dave's MousePanel Demo" );
	}
	
	public void attachMenuBar()
	{
		JMenuItem item;
		JMenu menu;
		JMenuBar menuBar = new JMenuBar();
		
		// ============== File menu
		menu = new JMenu( "File" );
		
		// Exit
		item = new JMenuItem( "Exit" );
		item.addActionListener( new ActionListener() 
		{
			public void actionPerformed( ActionEvent event )	// run on EDT
			{
				System.exit( 0 );
			}
		});
		menu.add( item );
		
		// attach menu to menu bar
		menuBar.add( menu );
		
		// =============== Panel Ops menu
		menu = new JMenu( "Panel ops" );
		
		// clear panel
		item = new JMenuItem( "Clear panel" );
		item.addActionListener( new ActionListener() 
		{
			public void actionPerformed( ActionEvent event )	// run on EDT
			{
				panel.clear( Color.WHITE );
			}
		});
		menu.add( item );
		
		// panel
		item = new JMenuItem( "Deactivate panel" );
		item.addActionListener( new ActionListener()
		{
			public void actionPerformed( ActionEvent event )	// run on EDT
			{
				panel.unregisterListeners();
			}
		});
		menu.add( item );
		
		// panel
		item = new JMenuItem( "Reactivate panel" );
		item.addActionListener( new ActionListener()
		{
			public void actionPerformed( ActionEvent event )	// run on EDT
			{
				panel.registerListeners();
			}
		});
		menu.add( item );
		
		// attach menu to menu bar
		menuBar.add( menu );
		
		
		// =============== Task Menu
		menu = new JMenu( "Task" );
		
		// Short Job
		item = new JMenuItem( "Random color (quick job)" );
		item.addActionListener( new ActionListener()
		{
			public void actionPerformed( ActionEvent event )	// run on EDT
			{
				// because this code is executed in response to an ActionEvent,
				// it is executed on the EDT; that's OK for a QUICK task
				changeColor();
			}
		});
		menu.add( item );
		
		// Random color (long job -- GUI Blocking)
		item = new JMenuItem( "Random color (long job -- GUI Blocking)" );
		item.addActionListener( new ActionListener() 
		{
			public void actionPerformed( ActionEvent event )	// run on EDT
			{
				// because this code is executed in response to an ActionEvent
				// it is executed on the EDT; it's a TERRIBLE idea for a "long"
				// task to be executed by the EDT as it will block the GUI
				changeColorBlocking();
			}
		});
		menu.add( item );
		
		// Random color (long job -- NOT GUI Blocking)
		item = new JMenuItem( "Random color (long job - not GUI Blocking" );
		item.addActionListener( new ActionListener() 
		{
			public void actionPerformed( ActionEvent event )	// run on EDT
			{
				// because this code is executed in response to an ActionEvent
				// it is executed on the EDT; it's a TERRIBLE idea for a "long"
				// task to be executed by the EDT as it will block the GUI
				changeColorNonBlocking();
			}
		});
		menu.add( item );
		
		// attach menu to menu bar
		menuBar.add( menu );
		
		// attach menu to menu bar
		this.setJMenuBar( menuBar );
	}
	
	//=========================================================================
	// makeButton()
	
	private JButton makeButton()
	{
		final JButton button = new JButton( "Press to reset" );
		button.addActionListener( new ActionListener() 
		{
			public void actionPerformed( ActionEvent event )
			{
				panel.clear( Color.WHITE );
			}
		});
		return button;
	}
	
	//=========================================================================
	// changeColor()
	
	private void changeColor()
	{
		// change the panel to a random color
		panel.clear( new Color( rand.nextInt( 0x01000000 )));
	}
	
	//=========================================================================
	// long task invoked by GUI event: take 1					 *** BAD! ***
	//
	// how NOT to write code that will be invoked by the EDT that will take a 
	// LONG time to execute
	
	private void changeColorBlocking()
	{
		// simulate a "long" process by burning time
		try
		{
			Thread.sleep( DURATION );
		}
		catch ( InterruptedException e )
		{
			// swallow the exception, this is bad!!!
		}
		
		// update the GUI
		changeColor();
	}
	
	//=========================================================================
	// long task invoked by GUI event: take 2					*** GOOD! ***
	//
	// HOW TO write code that will be invoked by the EDT that will take a "long"
	// time to execute
	
	private void changeColorNonBlocking()
	{
		// idea: spin thread to do the long task, then display the results using
		// a task passed BACK to the EDT
		
		new Thread( new Runnable()
		{
			public void run()
			{
				// simulate a "long" process by burning time
				try
				{
					Thread.sleep( DURATION );
				}
				catch ( InterruptedException e )
				{
					// swallow the exception, this is BAD!!!!
				}
				
				// update what the user sees [puts task on the EDT]	
				// using invokeLater puts this task on the EDT once all
				// other pending tasks are complete
				SwingUtilities.invokeLater( new Runnable()	// run on EDT
				{
					public void run()
					{
						changeColor();
					}
				});
			}
		}).start(); // kicks off this thread. Will sleep, and then run the
					// changeColor() operation
	}
}
